﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Mathematics;

namespace NetTopologySuite.Algorithm
{
	public static class CGAlgorithms
	{
		public static int OrientationIndex(Coordinate p1, Coordinate p2, Coordinate q)
		{
			return CGAlgorithmsDD.OrientationIndex(p1, p2, q);
		}

		public static bool IsPointInRing(Coordinate p, Coordinate[] ring)
		{
			return CGAlgorithms.LocatePointInRing(p, ring) != Location.Exterior;
		}

		public static bool IsPointInRing(Coordinate p, ICoordinateSequence ring)
		{
			return CGAlgorithms.LocatePointInRing(p, ring) != Location.Exterior;
		}

		public static Location LocatePointInRing(Coordinate p, Coordinate[] ring)
		{
			return RayCrossingCounter.LocatePointInRing(p, ring);
		}

		public static Location LocatePointInRing(Coordinate p, ICoordinateSequence ring)
		{
			return RayCrossingCounter.LocatePointInRing(p, ring);
		}

		public static bool IsOnLine(Coordinate p, Coordinate[] pt)
		{
			LineIntersector lineIntersector = new RobustLineIntersector();
			for (int i = 1; i < pt.Length; i++)
			{
				Coordinate p2 = pt[i - 1];
				Coordinate p3 = pt[i];
				lineIntersector.ComputeIntersection(p, p2, p3);
				if (lineIntersector.HasIntersection)
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsCCW(Coordinate[] ring)
		{
			int num = ring.Length - 1;
			if (num < 3)
			{
				throw new ArgumentException("Ring has fewer than 4 points, so orientation cannot be determined");
			}
			Coordinate coordinate = ring[0];
			int num2 = 0;
			for (int i = 1; i <= num; i++)
			{
				Coordinate coordinate2 = ring[i];
				if (coordinate2.Y > coordinate.Y)
				{
					coordinate = coordinate2;
					num2 = i;
				}
			}
			int num3 = num2;
			do
			{
				num3--;
				if (num3 < 0)
				{
					num3 = num;
				}
			}
			while (ring[num3].Equals2D(coordinate) && num3 != num2);
			int num4 = num2;
			do
			{
				num4 = (num4 + 1) % num;
			}
			while (ring[num4].Equals2D(coordinate) && num4 != num2);
			Coordinate coordinate3 = ring[num3];
			Coordinate coordinate4 = ring[num4];
			if (coordinate3.Equals2D(coordinate) || coordinate4.Equals2D(coordinate) || coordinate3.Equals2D(coordinate4))
			{
				return false;
			}
			int num5 = CGAlgorithms.ComputeOrientation(coordinate3, coordinate, coordinate4);
			bool result;
			if (num5 == 0)
			{
				result = (coordinate3.X > coordinate4.X);
			}
			else
			{
				result = (num5 > 0);
			}
			return result;
		}

		public static bool IsCCW(ICoordinateSequence ring)
		{
			return CGAlgorithms.IsCCW(ring.ToCoordinateArray());
		}

		public static int ComputeOrientation(Coordinate p1, Coordinate p2, Coordinate q)
		{
			return CGAlgorithms.OrientationIndex(p1, p2, q);
		}

		public static double DistancePointLine(Coordinate p, Coordinate A, Coordinate B)
		{
			if (A.X == B.X && A.Y == B.Y)
			{
				return p.Distance(A);
			}
			double num = (B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y);
			double num2 = ((p.X - A.X) * (B.X - A.X) + (p.Y - A.Y) * (B.Y - A.Y)) / num;
			if (num2 <= 0.0)
			{
				return p.Distance(A);
			}
			if (num2 >= 1.0)
			{
				return p.Distance(B);
			}
			return System.Math.Abs(((A.Y - p.Y) * (B.X - A.X) - (A.X - p.X) * (B.Y - A.Y)) / num) * System.Math.Sqrt(num);
		}

		public static double DistancePointLinePerpendicular(Coordinate p, Coordinate A, Coordinate B)
		{
			double num = (B.X - A.X) * (B.X - A.X) + (B.Y - A.Y) * (B.Y - A.Y);
			return System.Math.Abs(((A.Y - p.Y) * (B.X - A.X) - (A.X - p.X) * (B.Y - A.Y)) / num) * System.Math.Sqrt(num);
		}

		public static double DistancePointLine(Coordinate p, Coordinate[] line)
		{
			if (line.Length == 0)
			{
				throw new ArgumentException("Line array must contain at least one vertex");
			}
			double num = p.Distance(line[0]);
			for (int i = 0; i < line.Length - 1; i++)
			{
				double num2 = CGAlgorithms.DistancePointLine(p, line[i], line[i + 1]);
				if (num2 < num)
				{
					num = num2;
				}
			}
			return num;
		}

		public static double DistanceLineLine(Coordinate A, Coordinate B, Coordinate C, Coordinate D)
		{
			if (A.Equals(B))
			{
				return CGAlgorithms.DistancePointLine(A, C, D);
			}
			if (C.Equals(D))
			{
				return CGAlgorithms.DistancePointLine(D, A, B);
			}
			bool flag = false;
			if (!Envelope.Intersects(A, B, C, D))
			{
				flag = true;
			}
			else
			{
				double num = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X);
				if (num == 0.0)
				{
					flag = true;
				}
				else
				{
					double num2 = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y);
					double num3 = ((A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y)) / num;
					double num4 = num2 / num;
					if (num4 < 0.0 || num4 > 1.0 || num3 < 0.0 || num3 > 1.0)
					{
						flag = true;
					}
				}
			}
			if (flag)
			{
				return MathUtil.Min(CGAlgorithms.DistancePointLine(A, C, D), CGAlgorithms.DistancePointLine(B, C, D), CGAlgorithms.DistancePointLine(C, A, B), CGAlgorithms.DistancePointLine(D, A, B));
			}
			return 0.0;
		}

		public static double SignedArea(Coordinate[] ring)
		{
			if (ring.Length < 3)
			{
				return 0.0;
			}
			double num = 0.0;
			double x = ring[0].X;
			for (int i = 1; i < ring.Length - 1; i++)
			{
				double num2 = ring[i].X - x;
				double y = ring[i + 1].Y;
				double y2 = ring[i - 1].Y;
				num += num2 * (y2 - y);
			}
			return num / 2.0;
		}

		public static double SignedArea(ICoordinateSequence ring)
		{
			int count = ring.Count;
			if (count < 3)
			{
				return 0.0;
			}
			Coordinate coordinate = new Coordinate();
			Coordinate coordinate2 = new Coordinate();
			Coordinate coordinate3 = new Coordinate();
			ring.GetCoordinate(0, coordinate2);
			ring.GetCoordinate(1, coordinate3);
			double x = coordinate2.X;
			coordinate3.X -= x;
			double num = 0.0;
			for (int i = 1; i < count - 1; i++)
			{
				coordinate.Y = coordinate2.Y;
				coordinate2.X = coordinate3.X;
				coordinate2.Y = coordinate3.Y;
				ring.GetCoordinate(i + 1, coordinate3);
				coordinate3.X -= x;
				num += coordinate2.X * (coordinate.Y - coordinate3.Y);
			}
			return num / 2.0;
		}

		public static double Length(ICoordinateSequence pts)
		{
			int count = pts.Count;
			if (count <= 1)
			{
				return 0.0;
			}
			double num = 0.0;
			Coordinate coordinate = new Coordinate();
			pts.GetCoordinate(0, coordinate);
			double num2 = coordinate.X;
			double num3 = coordinate.Y;
			for (int i = 1; i < count; i++)
			{
				pts.GetCoordinate(i, coordinate);
				double x = coordinate.X;
				double y = coordinate.Y;
				double num4 = x - num2;
				double num5 = y - num3;
				num += System.Math.Sqrt(num4 * num4 + num5 * num5);
				num2 = x;
				num3 = y;
			}
			return num;
		}

		public const int Clockwise = -1;

		public const int Right = -1;

		public const int CounterClockwise = 1;

		public const int Left = 1;

		public const int Collinear = 0;

		public const int Straight = 0;
	}
}
